#ifndef _WX_DIRCTRL_H_
#define _WX_DIRCTRL_H_

#if wxUSE_DIRDLG || wxUSE_FILEDLG
#include "wx/imaglist.h"
#endif

#include "wx/treectrl.h"
#include "wx/dialog.h"
#include "wx/dirdlg.h"
#include "wx/choice.h"

class wxTextCtrl;
class wxImageList;
class wxHashTable;

enum {
  // Only allow directory viewing/selection, no files
  wxDIRCTRL_DIR_ONLY       = 0x0010,
  // When setting the default path, select the first file in the directory
  wxDIRCTRL_SELECT_FIRST   = 0x0020,
  // Show the filter list
  wxDIRCTRL_SHOW_FILTERS   = 0x0040,
  // Use 3D borders on internal controls
  wxDIRCTRL_3D_INTERNAL    = 0x0080,
  // Editable labels
  wxDIRCTRL_EDIT_LABELS    = 0x0100
};

class wxDirItemData : public wxTreeItemData {
  public:
    wxDirItemData( const wxString& path, const wxString& name, bool isDir );
    virtual ~wxDirItemData() {}
    void SetNewDirName( const wxString& path );

    bool HasSubDirs() const;
    bool HasFiles( const wxString& spec = wxEmptyString ) const;

    wxString m_path, m_name;
    bool m_isHidden;
    bool m_isExpanded;
    bool m_isDir;
};

class wxDirFilterListCtrl;

class wxGenericDirCtrl: public wxControl {
  public:
    wxGenericDirCtrl();
    wxGenericDirCtrl( wxWindow *parent, const wxWindowID id = wxID_ANY,
                      const wxString &dir = wxDirDialogDefaultFolderStr,
                      const wxPoint& pos = wxDefaultPosition,
                      const wxSize& size = wxDefaultSize,
                      long style = wxDIRCTRL_3D_INTERNAL | wxSUNKEN_BORDER,
                      const wxString& filter = wxEmptyString,
                      int defaultFilter = 0,
                      const wxString& name = wxTreeCtrlNameStr ) {
      Init();
      Create( parent, id, dir, pos, size, style, filter, defaultFilter, name );
    }

    bool Create( wxWindow *parent, const wxWindowID id = wxID_ANY,
                 const wxString &dir = wxDirDialogDefaultFolderStr,
                 const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize,
                 long style = wxDIRCTRL_3D_INTERNAL | wxSUNKEN_BORDER,
                 const wxString& filter = wxEmptyString,
                 int defaultFilter = 0,
                 const wxString& name = wxTreeCtrlNameStr );

    virtual void Init();

    virtual ~wxGenericDirCtrl();

    void OnExpandItem( wxTreeEvent &event );
    void OnCollapseItem( wxTreeEvent &event );
    void OnBeginEditItem( wxTreeEvent &event );
    void OnEndEditItem( wxTreeEvent &event );
    void OnSize( wxSizeEvent &event );

    // Try to expand as much of the given path as possible.
    virtual bool ExpandPath( const wxString& path );
    // collapse the path
    virtual bool CollapsePath( const wxString& path );

    // Accessors

    virtual inline wxString GetDefaultPath() const { return m_defaultPath; }
    virtual void SetDefaultPath( const wxString& path ) { m_defaultPath = path; }

    // Get dir or filename
    virtual wxString GetPath() const;

    // Get selected filename path only (else empty string).
    // I.e. don't count a directory as a selection
    virtual wxString GetFilePath() const;
    virtual void SetPath( const wxString& path );

    virtual void ShowHidden( bool show );
    virtual bool GetShowHidden() { return m_showHidden; }

    virtual wxString GetFilter() const { return m_filter; }
    virtual void SetFilter( const wxString& filter );

    virtual int GetFilterIndex() const { return m_currentFilter; }
    virtual void SetFilterIndex( int n );

    virtual wxTreeItemId GetRootId() { return m_rootId; }

    virtual wxTreeCtrl* GetTreeCtrl() const { return m_treeCtrl; }
    virtual wxDirFilterListCtrl* GetFilterListCtrl() const { return m_filterListCtrl; }

    // Helper
    virtual void SetupSections();
    virtual wxTreeItemId FindChild( wxTreeItemId parentId, const wxString& path, bool& done );
    virtual void DoResize();
    virtual void ReCreateTree();
    virtual void CollapseTree();

  protected:
    virtual void ExpandRoot();
    virtual void ExpandDir( wxTreeItemId parentId );
    virtual void CollapseDir( wxTreeItemId parentId );
    virtual const wxTreeItemId AddSection( const wxString& path, const wxString& name, int imageId = 0 );
    virtual wxTreeItemId AppendItem( const wxTreeItemId & parent,
                                     const wxString & text,
                                     int image = -1, int selectedImage = -1,
                                     wxTreeItemData * data = NULL );
    //void FindChildFiles(wxTreeItemId id, int dirFlags, wxArrayString& filenames);
    virtual wxTreeCtrl* CreateTreeCtrl( wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long treeStyle );
    bool ExtractWildcard( const wxString& filterStr, int n, wxString& filter, wxString& description );

  private:
    bool            m_showHidden;
    wxTreeItemId    m_rootId;
    wxString        m_defaultPath; // Starting path
    long            m_styleEx; // Extended style
    wxString        m_filter;  // Wildcards in same format as per wxFileDialog
    int             m_currentFilter; // The current filter index
    wxString        m_currentFilterStr; // Current filter string
    wxTreeCtrl*     m_treeCtrl;
    wxDirFilterListCtrl* m_filterListCtrl;

  private:
    DECLARE_EVENT_TABLE()
    DECLARE_DYNAMIC_CLASS( wxGenericDirCtrl )
    DECLARE_NO_COPY_CLASS( wxGenericDirCtrl )
};

class wxDirFilterListCtrl: public wxChoice {
  public:
    wxDirFilterListCtrl() { Init(); }
    wxDirFilterListCtrl( wxGenericDirCtrl* parent, const wxWindowID id = wxID_ANY,
                         const wxPoint& pos = wxDefaultPosition,
                         const wxSize& size = wxDefaultSize,
                         long style = 0 ) {
      Init();
      Create( parent, id, pos, size, style );
    }

    bool Create( wxGenericDirCtrl* parent, const wxWindowID id = wxID_ANY,
                 const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize,
                 long style = 0 );

    void Init();
    virtual ~wxDirFilterListCtrl() {}
    void FillFilterList( const wxString& filter, int defaultFilter );
    void OnSelFilter( wxCommandEvent& event );
  protected:
    wxGenericDirCtrl*    m_dirCtrl;
    DECLARE_EVENT_TABLE()
    DECLARE_CLASS( wxDirFilterListCtrl )
    DECLARE_NO_COPY_CLASS( wxDirFilterListCtrl )
};

#define wxID_TREECTRL          7000
#define wxID_FILTERLISTCTRL    7001

class wxFileIconsTable {
  public:
    wxFileIconsTable();
    ~wxFileIconsTable();
    enum iconId_Type {
      folder,
      folder_open,
      computer,
      drive,
      cdrom,
      floppy,
      removeable,
      file,
      executable
    };
    int GetIconID( const wxString& extension, const wxString& mime = wxEmptyString );
    wxImageList *GetSmallImageList();
  protected:
    void Create();  // create on first use
    wxImageList *m_smallImageList;
    wxHashTable *m_HashTable;
};

extern wxFileIconsTable * wxTheFileIconsTable;

#endif
